﻿using System;
using System.Collections.Generic;
using System.Text;

namespace PVP
{
    class Rotate
    {
        struct commbination
        {
            public string key1;
            public string key2;
            public string key3;
            public string key4;
            public commbination(string key1, string key2, string key3, string key4)
            {
                this.key1 = key1;
                this.key2 = key2;
                this.key3 = key3;
                this.key4 = key4;
            }
        }

        struct parameter
        {
            public double cosa;
            public double sina;
            public double offsetX;
            public double offsetY;
            public parameter(double cosa, double sina, double offsetX, double offsetY)
            {
                this.cosa = cosa;
                this.sina = sina;
                this.offsetX = offsetX;
                this.offsetY = offsetY;

            }
        }

        public double cosa = 0.0;
        public double sina = 0.0;
        public double offsetX = 0.0;
        public double offsetY = 0.0;
        SortedList<string, Point2D> surveyGrp = new SortedList<string, Point2D>();
        public SortedList<string, Point2D> ConvertedsurveyGrp = new SortedList<string, Point2D>();
        private List<commbination> comlist = new List<commbination>();
        private List<parameter> paralist = new List<parameter>();

        public Rotate(SortedList<string, Point2D> oldlist, SortedList<string, Point2D> newlist, SortedList<string, Point2D> surveyGrp)
        {
            this.surveyGrp = surveyGrp;
            keycommbination(oldlist, newlist);

            foreach (commbination c in comlist)
            {
                RotateSingle(oldlist[c.key1], oldlist[c.key2], newlist[c.key1], newlist[c.key2]);
            }
            //RotateSingle(oldlist["301431"], oldlist["301432"], newlist["301431"], newlist["301432"]);
            getBest();
            PNTrotate();
        }

        public void test()
        {

        }

        public void getBest()
        {
            double sumcosa = 0.0;
            double sumsina = 0.0;
            double sumoffsetX = 0.0;
            double sumoffsetY = 0.0;

            for (int i = 0; i < paralist.Count; i++)
            {
                sumcosa += paralist[i].cosa;
                sumsina += paralist[i].sina;
                sumoffsetX += paralist[i].offsetX;
                sumoffsetY += paralist[i].offsetY;
            }
            cosa = sumcosa / paralist.Count;
            sina = sumsina / paralist.Count;
            offsetX = sumoffsetX / paralist.Count;
            offsetY = sumoffsetY / paralist.Count;
        }

        public void keycommbination(SortedList<string, Point2D> oldlist, SortedList<string, Point2D> newlist)
        {
            commbination co;
            for (int i = 0; i < oldlist.Count - 1; i++)
            {
                for (int j = i + 1; j < oldlist.Count; j++)
                {
                    co = new commbination(oldlist.Keys[i], oldlist.Keys[j], newlist.Keys[i], newlist.Keys[j]);
                    comlist.Add(co);
                }
            }
        }

        public void RotateSingle(Point2D oldp1, Point2D oldp2, Point2D newp1, Point2D newp2)
        {
            double Q = oldp1.X - oldp2.X;
            double W = oldp1.Y - oldp2.Y;
            double M = newp1.X - newp2.X;
            double N = newp1.Y - newp2.Y;

            double sina = (W * M - N * Q) / (M * M + N * N);
            double cosa = ((N * sina) + Q) / M;
            double offsetX = (oldp1.X - newp1.X * cosa + newp1.Y * sina);
            double offsetY = (oldp1.Y - newp1.X * sina - newp1.Y * cosa);

            parameter pa = new parameter(sina, cosa, offsetX, offsetY);

            paralist.Add(pa);
        }


        public void PNTrotate()
        {
            Point2D pt = new Point2D();
            double x = 0.0;
            double y = 0.0;
            foreach (KeyValuePair<string, Point2D> kvp in surveyGrp)
            {
                pt = kvp.Value;
                x = pt.X * cosa - pt.Y * sina + offsetX;
                y = pt.X * sina + pt.Y * cosa + offsetY;
                ConvertedsurveyGrp.Add(kvp.Key, new Point2D(x, y));
            }
        }
    }
}
